from django.core.paginator import Paginator
from django.core.serializers import serialize

from .time_conversion import datetime_to_times
from .time_conversion import iso_to_times

from ..models.chat_history import ChatHistory
from ..models.chat_roles import ChatRoles
from ..models.users import UsersGroup
from ..models.users import Users

import ast
import os
import geoip2.database
import json
import base64
import qrcode
import io
import re
import random
import string

from datetime import datetime
import time


def user_alluser_data_paging(userid):
    '''
    获取这个用户 所绑定的用户组信息
    {
        "groupid": [2, 3, 22, 77, 999],
        "options": [
            "key": groupid,
            "value": groupid,
            "label": groupname
        ],
    }
    '''
    usergroup_tree = {
        "groupid": [],
        "options": []
    }
    
    user_obj = Users.objects.get(id=userid)
    usergroup_obj = user_obj.userList.all()

    for usergroup in usergroup_obj:
        usergroup_tree['groupid'].append(usergroup.id)

        usergroup_tree['options'].append({
            "key": usergroup.id,
            "label": usergroup.groupname,
            "value": usergroup.id,
            "disabled": True
        })

    return usergroup_tree


def user_getroles(all_usergroup_obj, users_mes, gettype):
    # 查询用户是否有绑定用户组
    if all_usergroup_obj:
        # print('有用户组')
        one_usergroup_obj = all_usergroup_obj[0]
        if gettype == "roles":
            return ast.literal_eval(one_usergroup_obj.chat_roles_json)
        else:
            return ast.literal_eval(one_usergroup_obj.chat_models_json)
    else:
        # print('无用户组')
        if gettype == "roles":
            return ast.literal_eval(users_mes.chat_roles_json)
        else:
            return ast.literal_eval(users_mes.chat_models_json)


def users_data_paging(all_instance_obj, page, page_size):
    paginator = Paginator(all_instance_obj, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for users_mes in page_obj:
        # all_usergroup_obj = users_mes.userList.all()
        tree.append({
            "id": users_mes.id,
            "created_at": datetime_to_times(users_mes.created_at),
            "updated_at": datetime_to_times(users_mes.updated_at),
            "username": users_mes.username,
            "nickname": users_mes.nickname,
            "avatar": users_mes.avatar,
            "salt": users_mes.salt,
            "power": users_mes.power,
            # "chat_roles": user_getroles(all_usergroup_obj, users_mes, "roles"),
            # "chat_models": user_getroles(all_usergroup_obj, users_mes, "models"),
            "chat_roles": ast.literal_eval(users_mes.chat_roles_json),
            "chat_models": ast.literal_eval(users_mes.chat_models_json),
            "expired_time": datetime_to_times(users_mes.expired_time),
            "status": users_mes.status,
            "last_login_at": datetime_to_times(users_mes.last_login_at),
            "last_login_ip": users_mes.last_login_ip,
            "vip": users_mes.vip,
            "chat_usersgroup": user_alluser_data_paging(users_mes.id)
        })

    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }
        
    return res_data


def usergroup_alluser_data_paging(groupid):
    '''
    获取这个用户组关联的所有 用户id 列表
    {
        "usersid": [2, 3, 22, 77, 999],
        "options": [
            "key": userid,
            "value": userid,
            "label": label_str
        ],
    }
    '''

    user_tree = {
        "usersid": [],
        "options": []
    }
    
    usergroup_obj = UsersGroup.objects.get(id=groupid)
    users_obj = usergroup_obj.users.all()

    for user in users_obj:
        user_tree['usersid'].append(user.id)

        label_str = '{}({})'.format(user.nickname, user.username)
        user_tree['options'].append({
            "key": user.id,
            "label": label_str,
            "value": user.id,
            "disabled": True
        })

    return user_tree


# 整理用户组数据
def usergroup_data_paging(all_usergroup_obj, page, page_size):
    paginator = Paginator(all_usergroup_obj, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    

    for group_mes in page_obj:
        tree.append({
            "id": group_mes.id,
            "created_at": datetime_to_times(group_mes.created_at),
            "updated_at": datetime_to_times(group_mes.updated_at),
            "groupname": group_mes.groupname,
            "user_expired_time": datetime_to_times(group_mes.user_expired_time),
            "chat_roles": ast.literal_eval(group_mes.chat_roles_json),
            "chat_models": ast.literal_eval(group_mes.chat_models_json),
            "status": group_mes.status,
            "chat_users": usergroup_alluser_data_paging(group_mes.id)
        })

    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }

    return res_data


def loginlog_data_paging(all_instance_obj, page, page_size):
    paginator = Paginator(all_instance_obj, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for loginlog_mes in page_obj:
        tree.append({
            "id": loginlog_mes.id,
            "created_at": datetime_to_times(loginlog_mes.created_at),
            "updated_at": datetime_to_times(loginlog_mes.updated_at),
            "user_id": loginlog_mes.user_id,
            "username": loginlog_mes.username,
            "login_address": loginlog_mes.login_address,
            "login_ip": loginlog_mes.login_ip
        })

    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }
        
    return res_data


# 计算 token 数
def calc_tokens(chat_text_str, chat_model):
    import tiktoken

    # 使用 tiktoken.encoding_for_model 方法，获取该模型的标记化编码器
    try:
        encoding = tiktoken.encoding_for_model(chat_model)
    except:
        encoding = tiktoken.get_encoding("cl100k_base")

    # 先提取文字
    from bs4 import BeautifulSoup
    chat_text = BeautifulSoup(chat_text_str, 'html.parser')
    text = chat_text.get_text()
    chat_text = text.strip()

    # 使用编码器的 encode 方法，对输入的 text 进行标记化处理，得到一个标记列表
    tokens = encoding.encode(chat_text)

    # 计算标记列表的长度，即标记的数量
    token_count = len(tokens)
    
    # 返回标记的数量
    return token_count


# 获取ip地址的信息
def query_ip_location(ip_address, locales='zh-CN'):
    """
    查询IP地址的地理位置信息
    :param ip_address: IP地址
    :param locales: 国际化（如果locales不指定的话会默认输出英文我这里指定了中文）
    :return: 返回IP信息
    """

    #db_path = os.path.dirname(__file__) + '/Country.mmdb'
    db_path = r'./GeoLite2-City.mmdb'
    if not os.path.exists(db_path):
        raise FileNotFoundError('GeoLite2-City数据库不存在')
    try:
        with geoip2.database.Reader(db_path, locales=[locales]) as reader:
            response = reader.city(ip_address)
            location_info = {
                'country_name': response.country.name,  # 国家名称，中文显示
                'country_iso_code': response.country.iso_code,  # 国家ISO代码
                'province_name': response.subdivisions.most_specific.name,  # 省份名称，中文显示
                'province_iso_code': response.subdivisions.most_specific.iso_code,  # 省份ISO代码
                'city_name': response.city.name,  # 城市名称，中文显示
                'postal_code': response.postal.code,  # 邮政编码
                'latitude': response.location.latitude,  # 纬度
                'longitude': response.location.longitude,  # 经度
                'time_zone': response.location.time_zone,  # 时区
                'continent_name': response.continent.name,  # 大陆名称，中文显示
                'continent_code': response.continent.code  # 大陆代码
            }
            return location_info
    except Exception as e:
        # print(f"查询IP地址时发生错误: {e}")
        return {}
    

def chatslist_rolelost(roleid):
    all_chatroles = ChatRoles.objects.filter(id=roleid)


    json_data_str = serialize('json', all_chatroles)
    json_data = json.loads(json_data_str)

    role_mes = json_data[0]
    # 增加id属性
    role_mes['fields']['id'] = role_mes['pk']

    # 数据处理 时间处理
    created_at_second = iso_to_times(role_mes['fields']['created_at'])
    updated_at_second = iso_to_times(role_mes['fields']['updated_at'])
    role_mes['fields']['created_at'] = created_at_second
    role_mes['fields']['updated_at'] = updated_at_second

    # 处理context字段
    if role_mes['fields']['context']:
        context_str_dumps = role_mes['fields']['context']
        context_list_loads = json.loads(context_str_dumps)
        role_mes['fields']['context'] = context_list_loads

    # 连表查询key name
    if role_mes['fields']['model_id'] is None:
        role_mes['fields']['model_id'] = 0
        role_mes['fields']['model_name'] = ""
    else:
        role_mes['fields']['model_name'] = role_mes.model_id.name

    return role_mes['fields']


def chatslist_chatstoken(chatid):
    tokens = 0
    all_chathistory_obj = ChatHistory.objects.filter(chat_id=chatid)
    if all_chathistory_obj:
        for chathistory in all_chathistory_obj:
            tokens += chathistory.tokens

    return tokens


# 对话管理数据处理
def chatslist_handler(all_chatitems, page, page_size):
    paginator = Paginator(all_chatitems, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for chats_mes in page_obj:
        tree.append({
            "id": chats_mes.id,
            "chat_id": chats_mes.chat_id,
            "user_id": chats_mes.user_id,
            "role": chatslist_rolelost(chats_mes.role_id),
            "username": chats_mes.username,
            "model": chats_mes.model,
            "token": chatslist_chatstoken(chats_mes.chat_id),
            "title": chats_mes.title,
            "created_at": datetime_to_times(chats_mes.created_at),
            "msg_num": len(ChatHistory.objects.filter(chat_id=chats_mes.chat_id)),
        })


    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }
        
    return res_data


def chatsmessage_handler(all_chatsmessage, page, page_size):
    paginator = Paginator(all_chatsmessage, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for chats_mes in page_obj:
        tree.append({
            "id": chats_mes.id,
            "content": chats_mes.content,
            "created_at": datetime_to_times(chats_mes.created_at),
            "icon": chats_mes.icon,
            "model": chats_mes.model,
            "token": chats_mes.tokens,
            "type": chats_mes.type,
            "user_id": chats_mes.user_id,
            "username": chats_mes.username,
        })


    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }
        
    return res_data


def powertype(type_num):
    if type_num == 1:
        return "充值"
    elif type_num == 2:
        return "消费"
    elif type_num == 3:
        return "退款"
    elif type_num == 5:
        return "众筹"
    elif type_num == 7:
        return "兑换码"
    else:
        return "其他"


def chatpowerlogs_handler(all_chatpowerlogs, page, page_size):
    paginator = Paginator(all_chatpowerlogs, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for powerlogs_mes in page_obj:
        tree.append({
            "id": powerlogs_mes.id,
            "amount": powerlogs_mes.amount,
            "balance": powerlogs_mes.balance,
            "created_at": datetime_to_times(powerlogs_mes.created_at),
            "mark": int(powerlogs_mes.mark),
            "model": powerlogs_mes.model,
            "remark": powerlogs_mes.remark,
            "type": powerlogs_mes.type,
            "type_str": powertype(int(powerlogs_mes.type)),
            "user_id" : powerlogs_mes.user_id,
            "username": powerlogs_mes.username,
        })

    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }

    return res_data


def chatorders_handler(all_chatorders, page, page_size):
    paginator = Paginator(all_chatorders, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for chatorders_mes in page_obj:
        tree.append({
            "id": chatorders_mes.id,
            "user_id": chatorders_mes.user_id,
            "product_id": chatorders_mes.product_id,
            "username": chatorders_mes.username,
            "order_no": chatorders_mes.order_no,
            "trade_no": chatorders_mes.trade_no,
            "subject": chatorders_mes.subject,
            "amount": chatorders_mes.amount,
            "status": chatorders_mes.status,
            "remark": chatorders_mes.remark,
            "pay_time": datetime_to_times(chatorders_mes.pay_time),
            # "pay_way": chatorders_mes.pay_way,
            "pay_way": {"payjs": "微信", "alipay": "支付宝"}.get(chatorders_mes.pay_way, "unknown"),
            "created_at": datetime_to_times(chatorders_mes.created_at),
        })

    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }

    return res_data


def new_snowflake_id():
    '''
    生成一个新的唯一ID
    '''
    # 获取时间 到毫秒
    # 获取当前时间
    try:
        now = datetime.now()
        
        # 转换为时间戳，并保留毫秒
        timestamp_ms = int(round(time.mktime(now.timetuple()) * 1000) + now.microsecond / 1000)

        # 序列化日期：年份 + 月份（两位数） + 日期（两位数）
        serialized_date = f"{now.year}{now.month:02d}{now.day:02d}"

        # 时间戳往左移22位
        id = timestamp_ms << 22

        return '{}{}'.format(serialized_date, id)
    except:
        return 0
    

def gen_qrcode(code_url):
    '''
    将微信返回的code_url转换为base64的二维码
    '''
    try:
        img = qrcode.make(code_url)
        img = img.get_image()
        in_mem_file = io.BytesIO()
        img.save(in_mem_file, format="PNG")
        in_mem_file.seek(0)
        img_bytes = in_mem_file.read()
        base64_encoded_result_bytes = base64.b64encode(img_bytes)
        base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii')
        # print(base64_encoded_result_str)
        full_pr_code = 'data:image/png;base64,' +base64_encoded_result_str # 这里的png或其他格式可自定义

        return full_pr_code
    except:
        return ""


def is_mobile_number(phone_number):
    '''
    判断是否是手机号
    '''
    pattern = r'^1[3456789]\d{9}$'
    if re.match(pattern, str(phone_number)):
        return True
    else:
        return False
    

def generate_popular_chinese_nickname():
    '''
    生成随机昵称
    '''
    # 中文词汇库
    chinese_words = [
        "梦想", "飞翔", "微笑", "旅行", "风景", "阳光", "雨滴", "星辰", "浪漫", "快乐",
        "自由", "勇敢", "天使", "魔法", "幸福", "希望", "平安", "繁星", "花海", "蓝天",
        "白云", "萌萌", "可爱", "宝贝", "小鹿", "樱花", "冰淇淋", "巧克力", "糖果", "甜蜜",
        "橙子", "柠檬", "小熊", "天空", "海洋", "猫咪", "小狗", "麋鹿", "青草", "彩虹",
        "秋天", "冬雪", "春风", "夏海", "诗歌", "音乐", "书本", "灵魂", "梦境", "记忆",
        "微笑", "山丘", "善良", "温柔"
    ]

    # 随机选择两个词组合成昵称
    nickname = "".join(random.sample(chinese_words, 2))

    return nickname


def paginate(items, page_number, page_size):
    '''
    给一个列表分页
    '''
    start = (int(page_number) - 1) * int(page_size)
    end = start + int(page_size)
    # return items[start:end]

    total_pages = len(items) // int(page_size)
    if len(items) % int(page_size) > 0:
        total_pages += 1
    # return total_pages

    res_data = {
        "items": items[start:end],
        "page": int(page_number),
        "page_size": int(page_size),
        "total": len(items),
        "total_page": total_pages
    }

    return res_data


def chatredeem_handler(all_chatredeem, page, page_size):
    '''
    卡密数据处理
    '''
    paginator = Paginator(all_chatredeem, int(page_size))
    page_obj = paginator.get_page(int(page))

    # 整合数据
    tree = []
    for chatredeem_mes in page_obj:
        tree.append({
            "id": chatredeem_mes.id,
            "user_id": chatredeem_mes.user_id,
            "name": chatredeem_mes.name,
            "username": chatredeem_mes.username,
            "power": chatredeem_mes.power,
            "code": chatredeem_mes.code,
            "enabled": chatredeem_mes.enabled,
            "redeemed_at": datetime_to_times(chatredeem_mes.redeemed_at),
            "created_at": datetime_to_times(chatredeem_mes.created_at),
            "status": chatredeem_mes.status,
        })

    res_data = {
        "items": tree,
        "page": int(page),
        "page_size": int(page_size),
        "total": paginator.count,
        "total_page": paginator.num_pages
    }

    return res_data


def generate_random_string(length=32):
    """
    生成一个指定长度的随机字符串，包含小写字母和数字。
    
    :param length: 字符串的长度，默认为32
    :return: 随机生成的字符串
    """
    # 定义字符串的字符集，包括小写字母和数字
    characters = string.ascii_lowercase + string.digits
    # 使用random.choices从字符集中随机选择指定长度的字符
    random_string = ''.join(random.choices(characters, k=length))
    return random_string

